﻿using System.Collections;
using System.Collections.Generic;
using System;
using System.Linq;

public static class IEnumerableExt
{
    public static T[] ArrayAdd<T>(this T[] array, T value)
    {
        T[] newArray = new T[array.Length + 1];

        // 复制原始数组的元素到新数组
        Array.Copy(array, newArray, array.Length);

        // 在新数组中添加新元素
        newArray[newArray.Length - 1] = value;

        return newArray;
    }

    public static IEnumerable<T> AsEnumerable<T>(this T value)
    {
        yield return value;
    }

    public static T[] AsArray<T>(this IEnumerable<T> list)
    {
        return list.ToArray<T>();
    }

    public static List<T> AsList<T>(this IEnumerable<T> list)
    {
        if (list == null)
            return new List<T>();
        else
            return list.ToList<T>();
    }

    public static IEnumerable<R> Map<T, R>(this IEnumerable<T> list, Func<T, R> func)
    {
        if (null == list)
        {
            yield break;
        }

        foreach (T t in list)
        {
            var r = func(t);
            if (r != null)
                yield return r;
        }
        // return list.Select(func);
    }

    public static IEnumerable<ValueTuple> ForEach<T>(this IEnumerable<T> list, Action<T> action)
    {
        return list.Map(action.ToFunc()).ToList();//list.ForEach<T>((e) => { action(e); });
    }

    public static IEnumerable<R> Bind<T, R>(this IEnumerable<T> list, Func<T, IEnumerable<R>> func)
    {
        if (null == list)
        {
            throw new System.ArgumentNullException("Bind null == list");
        }
        if (null == func)
        {
            throw new System.ArgumentNullException("func null == list");
        }

        foreach (T t in list)
        {
            if (t != null)
            {
                var collection = func(t);
                if (collection != null)
                {
                    foreach (R r in collection)
                        if (r != null)
                            yield return r;
                }
            }
        }
    }

    public static IEnumerable<T> AllWhere<T>(this IEnumerable<T> list, Func<T, bool> predict)
    {
        return list.Where(predict);
    }


    public static int IndexOf<T>(this IEnumerable<T> list, Func<T, bool> equalFunc)
    {
        var enumerator = list.GetEnumerator();
        int index = 0;
        while (enumerator.MoveNext())
        {
            T cur = enumerator.Current;
            if (equalFunc(cur))
            {
                return index;
            }
            index++;
        }
        return -1;
    }

    public static T GetMin<T>(this IEnumerable<T> list, Func<T, float> getValue) where T : class
    {
        if (list.Count<T>() == 0)
            return null;

        T min = null;
        float curMinValue = float.MaxValue;
        foreach (var element in list)
        {
            if (getValue(element) < curMinValue)
            {
                curMinValue = getValue(element);
                min = element;
            }
        }
        return min;
    }
    public static T GetMax<T>(this IEnumerable<T> list, Func<T, float> getValue) where T : class
    {
        if (list.Count<T>() == 0)
            return null;

        T max = null;
        float curMaxValue = float.MinValue;
        foreach (var element in list)
        {
            if (getValue(element) > curMaxValue)
            {
                curMaxValue = getValue(element);
                max = element;
            }
        }
        return max;
    }



    public static T GetMinValue<T>(this IEnumerable<T> list, Func<T, float> getValue)
    {
        if (list.Count<T>() == 0)
            return default(T);

        T min = default(T);
        float curMinValue = int.MaxValue;
        foreach (var element in list)
        {
            if (getValue(element) < curMinValue)
            {
                curMinValue = getValue(element);
                min = element;
            }
        }
        return min;
    }


    public static T GetMaxValue<T>(this IEnumerable<T> list, Func<T, float> getValue)
    {
        if (list.Count<T>() == 0)
            return default(T);

        T max = default(T);
        float curMaxValue = float.NegativeInfinity;
        foreach (var element in list)
        {
            if (getValue(element) > curMaxValue)
            {
                curMaxValue = getValue(element);
                max = element;
            }
        }
        return max;
    }

}

